<?php

class Ev_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{

    /**
     * Called before an action is dispatched by Zend_Controller_Dispatcher.
     *
     * This callback allows for proxy or filter behavior.  By altering the
     * request and resetting its dispatched flag (via
     * {@link Zend_Controller_Request_Abstract::setDispatched() setDispatched(false)}),
     * the current action may be skipped.
     *
     * @param  Zend_Controller_Request_Abstract $request
     * @return void
     */
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        // Default role
        $sRole = 'publico';
        $oAuth = Zend_Auth::getInstance();
        if ($oAuth->hasIdentity()) {
            $oIdentity = $oAuth->getIdentity();
            $sRole     = $oIdentity->role;
        }

        $sModule     = $request->module;
        $sController = $request->controller;
        $sAction     = $request->action;
        $sResource   = $sModule . ':' . $sController . ':' . $sAction;

        $oAclIni = new Zend_Config_Ini(APPLICATION_PATH . '/configs/acl.ini', APPLICATION_ENV);
        $oAcl = $this->getAcl($oAclIni);

        Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($oAcl);
        Zend_View_Helper_Navigation_HelperAbstract::setDefaultRole($sRole);

        // Has resource in acl
        if (!$oAcl->has($sResource)) {
            //Zend_Log::log('Não existe o recurso [' . $sResource . ']', Zend_Log::LEVEL_SEVERE);
            return $this->_redirect('accessDeny', $request);
        }

        if($oAcl->isAllowed('publico', $sResource)) {
            return true;
        }

        // Access is not allowed
        if (!$oAcl->isAllowed($sRole, $sResource)) {
            // Redirect for method access deny
            if ($oAuth->hasIdentity()) {
                //Zend_Log::log('Acesso negado [' . $sResource . ']', Zend_Log::LEVEL_SEVERE);
                $page = 'accessDeny';
            } else {
                //Zend_Log::log('Redirecionado para logar [' . $sResource . ']', Zend_Log::LEVEL_SEVERE);
                // Redirect for method login
                $page = 'login';
            }
            return $this->_redirect($page, $request);
        }

        return true;
    }

    protected function _getConfigIni()
    {
        $cacheManager = Zend_Registry::get('Zend_Cache_Manager');
        if($cacheManager->hasCacheTemplate('acl')) {
            $aclCache = $cacheManager->getCache('acl');
            if($aclCache->test('aclIni')) {
                $oConfIni = $aclCache->load('aclIni');
            } else {
                $oConfIni = new Zend_Config_Ini( APPLICATION_PATH . '/configs/module.security.ini', APPLICATION_ENV );
                $aclCache->save($oConfIni, 'aclIni');
            }
        } else {
            $oConfIni = new Zend_Config_Ini( APPLICATION_PATH . '/configs/module.security.ini', APPLICATION_ENV );
        }
           return $oConfIni;
    }

    protected function _redirect($sRedirect, $request)
    {
        $flashMessenger = new Zend_Controller_Action_Helper_FlashMessenger();
        switch ($sRedirect) {
            case 'accessDeny' :
                $aRedirect = array('module'     => 'corporativo',
                                   'controller' => 'seguranca',
                                   'action'     => 'acesso-negado');
                $msg = 'Acesso negado';
                if (APPLICATION_ENV == 'development') {
                    $msg .= '[' . $request->getParam('module') . '/' .
                                  $request->getParam('controller') . '/' .
                                  $request->getParam('action') . ']';
                }
                $flashMessenger->addMessage($msg);
                break;
            case 'login' :
                $aRedirect = array('module'     => 'corporativo',
                                   'controller' => 'seguranca',
                                   'action'     => 'login');
                $flashMessenger->addMessage('Por favor, efetue o login');
                break;
        }

        $request->setModuleName($aRedirect['module']);
        $request->setControllerName($aRedirect['controller']);
        $request->setActionName($aRedirect['action']);
    }

    protected function getAcl(Zend_Config_Ini $oConfIni)
    {
        $oAcl  = new Zend_Acl();
        $aAcl = $oConfIni->acl->toArray();

        $oAcl->addRole('publico');
        $oAcl->addRole('comum', array('publico'));
        $oAcl->addRole('admin', array('comum'));

        foreach($aAcl as $sResource => $sRole) {
            // Add resources
            if (!$oAcl->has($sResource)) {
                $oAcl->add( new Zend_Acl_Resource($sResource));
            }

            // Add roles
            $aRole = explode('/', trim($sRole));
            foreach($aRole as $sRole) {
                if (!$oAcl->hasRole($sRole)) {
                    $oAcl->addRole(new Zend_Acl_Role($sRole));
                }
                $oAcl->allow($sRole, $sResource);
            }
        }
        return $oAcl;
    }

    public function log($msg, $code)
    {
        if($log = Zend_Registry::get('Zend_Log')) {
            $log->log($msg, $code);
            return $log;
        }
    }
}
